/* -------------------------------------------------------------------------------------------------------------------

 http://www.JSON.org/json2.js
 2008-03-24

 Public Domain.

 NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.

 See http://www.JSON.org/js.html

 This file creates a global JSON object containing three methods: stringify,
 parse, and quote.


 JSON.stringify(value, replacer, space)
 value       any JavaScript value, usually an object or array.

 replacer    an optional parameter that determines how object
 values are stringified for objects without a toJSON
 method. It can be a function or an array.

 space       an optional parameter that specifies the indentation
 of nested structures. If it is omitted, the text will
 be packed without extra whitespace. If it is a number,
 it will specify the number of spaces to indent at each
 level. If it is a string (such as '\t'), it contains the
 characters used to indent at each level.

 This method produces a JSON text from a JavaScript value.

 When an object value is found, if the object contains a toJSON
 method, its toJSON method will be called and the result will be
 stringified. A toJSON method does not serialize: it returns the
 value represented by the name/value pair that should be serialized,
 or undefined if nothing should be serialized. The toJSON method will
 be passed the key associated with the value, and this will be bound
 to the object holding the key.

 This is the toJSON method added to Dates:

 function toJSON(key) {
 return this.getUTCFullYear()   + '-' +
 f(this.getUTCMonth() + 1) + '-' +
 f(this.getUTCDate())      + 'T' +
 f(this.getUTCHours())     + ':' +
 f(this.getUTCMinutes())   + ':' +
 f(this.getUTCSeconds())   + 'Z';
 }

 You can provide an optional replacer method. It will be passed the
 key and value of each member, with this bound to the containing
 object. The value that is returned from your method will be
 serialized. If your method returns undefined, then the member will
 be excluded from the serialization.

 If no replacer parameter is provided, then a default replacer
 will be used:

 function replacer(key, value) {
 return Object.hasOwnProperty.call(this, key) ?
 value : undefined;
 }

 The default replacer is passed the key and value for each item in
 the structure. It excludes inherited members.

 If the replacer parameter is an array, then it will be used to
 select the members to be serialized. It filters the results such
 that only members with keys listed in the replacer array are
 stringified.

 Values that do not have JSON representaions, such as undefined or
 functions, will not be serialized. Such values in objects will be
 dropped; in arrays they will be replaced with null. You can use
 a replacer function to replace those with JSON values.
 JSON.stringify(undefined) returns undefined.

 The optional space parameter produces a stringification of the value
 that is filled with line breaks and indentation to make it easier to
 read.

 If the space parameter is a non-empty string, then that string will
 be used for indentation. If the space parameter is a number, then
 then indentation will be that many spaces.

 Example:

 text = JSON.stringify(['e', {pluribus: 'unum'}]);
 // text is '["e",{"pluribus":"unum"}]'


 text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
 // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'


 JSON.parse(text, reviver)
 This method parses a JSON text to produce an object or array.
 It can throw a SyntaxError exception.

 The optional reviver parameter is a function that can filter and
 transform the results. It receives each of the keys and values,
 and its return value is used instead of the original value.
 If it returns what it received, then the structure is not modified.
 If it returns undefined then the member is deleted.

 Example:

 // Parse the text. Values that look like ISO date strings will
 // be converted to Date objects.

 myData = JSON.parse(text, function (key, value) {
 var a;
 if (typeof value === 'string') {
 a =
 /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
 if (a) {
 return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
 +a[5], +a[6]));
 }
 }
 return value;
 });


 JSON.quote(text)
 This method wraps a string in quotes, escaping some characters
 as needed.


 This is a reference implementation. You are free to copy, modify, or
 redistribute.

 USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD THIRD PARTY
 CODE INTO YOUR PAGES.
 */

/*jslint regexp: true, forin: true, evil: true */

/*global JSON */

/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
 call, charCodeAt, floor, getUTCDate, getUTCFullYear, getUTCHours,
 getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, length,
 parse, propertyIsEnumerable, prototype, push, quote, replace, stringify,
 test, toJSON, toString
 */

if (!this.JSON) {
    JSON = function() {
        function f(n) {
            return n < 10 ? '0' + n: n;
        }
        Date.prototype.toJSON = function() {
            return this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z';
        };
        var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g,
            gap, indent, meta = {
                '\b': '\\b',
                '\t': '\\t',
                '\n': '\\n',
                '\f': '\\f',
                '\r': '\\r',
                '"': '\\"',
                '\\': '\\\\'
            },
            rep;
        function quote(string) {
            return escapeable.test(string) ? '"' + string.replace(escapeable,
                function(a) {
                    var c = meta[a];
                    if (typeof c === 'string') {
                        return c;
                    }
                    c = a.charCodeAt();
                    return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
                }) + '"': '"' + string + '"';
        }
        function str(key, holder) {
            var i, k, v, length, mind = gap,
                partial, value = holder[key];
            if (value && typeof value === 'object' && typeof value.toJSON === 'function') {
                value = value.toJSON(key);
            }
            if (typeof rep === 'function') {
                value = rep.call(holder, key, value);
            }
            switch (typeof value) {
                case 'string':
                    return quote(value);
                case 'number':
                    return isFinite(value) ? String(value) : 'null';
                case 'boolean':
                case 'null':
                    return String(value);
                case 'object':
                    if (!value) {
                        return 'null';
                    }
                    gap += indent;
                    partial = [];
                    if (typeof value.length === 'number' && !(value.propertyIsEnumerable('length'))) {
                        length = value.length;
                        for (i = 0; i < length; i += 1) {
                            partial[i] = str(i, value) || 'null';
                        }
                        v = partial.length === 0 ? '[]': gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']': '[' + partial.join(',') + ']';
                        gap = mind;
                        return v;
                    }
                    if (typeof rep === 'object') {
                        length = rep.length;
                        for (i = 0; i < length; i += 1) {
                            k = rep[i];
                            if (typeof k === 'string') {
                                v = str(k, value, rep);
                                if (v) {
                                    partial.push(quote(k) + (gap ? ': ': ':') + v);
                                }
                            }
                        }
                    } else {
                        for (k in value) {
                            v = str(k, value, rep);
                            if (v) {
                                partial.push(quote(k) + (gap ? ': ': ':') + v);
                            }
                        }
                    }
                    v = partial.length === 0 ? '{}': gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}': '{' + partial.join(',') + '}';
                    gap = mind;
                    return v;
            }
        }
        return {
            stringify: function(value, replacer, space) {
                var i;
                gap = '';
                indent = '';
                if (space) {
                    if (typeof space === 'number') {
                        for (i = 0; i < space; i += 1) {
                            indent += ' ';
                        }
                    } else if (typeof space === 'string') {
                        indent = space;
                    }
                }
                if (!replacer) {
                    rep = function(key, value) {
                        if (!Object.hasOwnProperty.call(this, key)) {
                            return undefined;
                        }
                        return value;
                    };
                } else if (typeof replacer === 'function' || (typeof replacer === 'object' && typeof replacer.length === 'number')) {
                    rep = replacer;
                } else {
                    throw new Error('JSON.stringify');
                }
                return str('', {
                    '': value
                });
            },
            parse: function(text, reviver) {
                var j;
                function walk(holder, key) {
                    var k, v, value = holder[key];
                    if (value && typeof value === 'object') {
                        for (k in value) {
                            if (Object.hasOwnProperty.call(value, k)) {
                                v = walk(value, k);
                                if (v !== undefined) {
                                    value[k] = v;
                                } else {
                                    delete value[k];
                                }
                            }
                        }
                    }
                    return reviver.call(holder, key, value);
                }
                if (/^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
                    j = eval('(' + text + ')');
                    return typeof reviver === 'function' ? walk({
                            '': j
                        },
                        '') : j;
                }
                throw new SyntaxError('JSON.parse');
            },
            quote: quote
        };
    } ();
}

/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
 * Licensed under the MIT License (LICENSE.txt).
 *
 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
 * Thanks to: Seamus Leahy for adding deltaX and deltaY
 *
 * Version: 3.0.6
 *
 * Requires: 1.2.2+
 */

(function($) {
    var types = ['DOMMouseScroll', 'mousewheel'];
    if ($.event.fixHooks) {
        for (var i = types.length; i;) {
            $.event.fixHooks[types[--i]] = $.event.mouseHooks;
        }
    }
    $.event.special.mousewheel = {
        setup: function() {
            if (this.addEventListener) {
                for (var i = types.length; i;) {
                    this.addEventListener(types[--i], handler, false);
                }
            } else {
                this.onmousewheel = handler;
            }
        },
        teardown: function() {
            if (this.removeEventListener) {
                for (var i = types.length; i;) {
                    this.removeEventListener(types[--i], handler, false);
                }
            } else {
                this.onmousewheel = null;
            }
        }
    };
    $.fn.extend({
        mousewheel: function(fn) {
            return fn ? this.on("mousewheel", fn) : this.trigger("mousewheel");
        },
        unmousewheel: function(fn) {
            return this.off("mousewheel", fn);
        }
    });
    function handler(event) {
        var orgEvent = event || window.event,
            args = [].slice.call(arguments, 1),
            delta = 0,
            returnValue = true,
            deltaX = 0,
            deltaY = 0;
        event = $.event.fix(orgEvent);
        event.type = "mousewheel";
        if (orgEvent.wheelDelta) {
            delta = orgEvent.wheelDelta / 120;
        }
        if (orgEvent.detail) {
            delta = -orgEvent.detail / 3;
        }
        deltaY = delta;
        if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
            deltaY = 0;
            deltaX = -1 * delta;
        }
        if (orgEvent.wheelDeltaY !== undefined) {
            deltaY = orgEvent.wheelDeltaY / 120;
        }
        if (orgEvent.wheelDeltaX !== undefined) {
            deltaX = -1 * orgEvent.wheelDeltaX / 120;
        }
        args.unshift(event, delta, deltaX, deltaY);
        return ($.event.dispatch || $.event.handle).apply(this, args);
    }
})(jQuery);



// Copyright (c) 2009 - 2010 Erik van den Berg (http://www.planitworks.nl/fwrContextMenu)
// Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
// and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
//
// Contributors:
// Denis Evteev
// Roman Imankulov (www.netangels.ru)
//
// Version: 1.3
// Requires jQuery 1.3.2+
_globalfwrContextMenuIgnoreHide = false;
(function($) {
    var _global;
    var _menus;

    // Detect overflow.
    var _overflow = function(x, y, containerElem) {
        /*var realWindowHeight = window.innerHeight ? window.innerHeight: $(window).height(); //fix bug on ios safari
         return {
         width: x - $(window).width() - $(window).scrollLeft(),
         height: y - realWindowHeight - $(window).scrollTop()
         };*/
        var jqContainerElem = $(containerElem);
        var realWindowHeight = containerElem.innerHeight ? containerElem.innerHeight: jqContainerElem.height(); //fix bug on ios safari
        var offset = jqContainerElem.offset();
        return {
            width: x - $(containerElem).width() - $(containerElem).scrollLeft() - offset.left,
            height: y - realWindowHeight - $(containerElem).scrollTop() - offset.top
        };
    };

    // Keyboard up/down
    var _onKeyUpDown = function(down) {
        if (_menus[_global.activeId].currentHover) {
            // Hover the first visible menu-item from the next or previous siblings and skip any separator items.
            var prevNext = down ? _menus[_global.activeId].currentHover.nextAll(':not(.' + _menus[_global.activeId].separatorClass + '):visible:first') : _menus[_global.activeId].currentHover.prevAll(':not(.' + _menus[_global.activeId].separatorClass + '):visible:first');
            // If nothing is found, hover the first or last visible sibling.
            if (prevNext.length == 0) {
                prevNext = _menus[_global.activeId].currentHover.parent().find('> li:visible');
                prevNext = (down ? $(prevNext[0]) : $(prevNext[prevNext.length - 1]));
            }
            prevNext.mouseover();
        } else {
            // Current hover is null, select the last visible submenu.
            var visibleMenus = $('#' + _global.activeId + ', #' + _global.activeId + ' ul').filter(function() {
                return ($(this).is(':visible') && $(this).parents(':hidden').length == 0);
            });
            if (visibleMenus.length > 0) {
                // Find all visible menu-items for this menu and hover the first or last visible sibling.
                var visibleItems = $(visibleMenus[visibleMenus.length - 1]).find('> li:visible');
                $(visibleItems[(down ? 0 : (visibleItems.length - 1))]).mouseover();
            }
        }
    };

    // Clear all active context.
    var _clearActive = function() {
        for (cm in _menus) {
            $(_menus[cm].allContext).removeClass(_global.activeClass);
        }
    };

    // Reset menu.
    var _resetMenu = function() {
        // Hide active menu and it's submenus.
        if (_global.activeId) $('#' + _global.activeId).add('#' + _global.activeId + ' ul').hide();
        // Stop key up/down interval.
        clearInterval(_global.keyUpDown);
        _global.keyUpDownStop = false;
        // Clear current hover.
        if (_menus[_global.activeId]) _menus[_global.activeId].currentHover = null;
        // Clear active menu.
        _global.activeId = null;
        // Unbind click and mouseover functions bound to the document
        $(document).off('.fwrContextMenu');
        // Unbind resize event bound to the window.
        $(window).off('resize.fwrContextMenu');
    };

    var _globalHide = function(e) {
        // Invoke onHide callback if set, 'this' refers to the menu.
        // Discontinue default behavior if callback returns false.
        if (_global.activeId && _menus[_global.activeId].onHide) {
            if (_menus[_global.activeId].onHide.apply($('#' + _global.activeId), [e, _menus[_global.activeId].context]) == false) {
                return false;
            }
        }

        // Default behavior.
        // =================================================== //
        // Clear active context.
        _clearActive();
        // Hide active menu.
        _resetMenu();
    };

    $.fn.fwrContextMenu = function(id, options, containerElem) {
        var _containerElem = containerElem || window;
        if (!_global) _global = {};
        if (!_menus) _menus = {};

        // Always override _global.menuClass if value is provided by options.
        if (options && options.menuClass) _global.menuClass = options.menuClass;
        // Only set _global.menuClass if not set.
        if (!_global.menuClass) _global.menuClass = 'fwrContextMenu';
        // Always override _global.activeClass if value is provided by options.
        if (options && options.activeClass) _global.activeClass = options.activeClass;
        // Only set _global.activeClass if not set.
        if (!_global.activeClass) _global.activeClass = 'active';

        // Default undefined:
        // livequery, bool
        // event, string
        // openBelowContext, bool
        // ignoreWidthOverflow, bool
        // ignoreHeightOverflow, bool
        // autoHide, bool
        // onShow, function
        // onHover, function
        // onSelect, function
        // onHide, function
        _menus[id] = $.extend({
                hoverClass: 'hover',
                submenuClass: 'submenu',
                separatorClass: 'separator',
                operaEvent: 'ctrl+click',
                fadeIn: 200,
                delay: 300,
                keyDelay: 100,
                widthOverflowOffset: 0,
                heightOverflowOffset: 0,
                submenuLeftOffset: 0,
                submenuTopOffset: 0,
                autoAddSubmenuArrows: true,
                startLeftOffset: 0,
                startTopOffset: 0,
                keyboard: true
            },
                options || {});

        // All context bound to this menu.
        _menus[id].allContext = this.selector;

        // Add mouseover and click handlers to the menu's items.
        $('#' + id).find('li')[_menus[id].livequery ? 'expire': 'unbind']('.fwrContextMenu')[_menus[id].livequery ? 'livequery': 'bind']('mouseover.fwrContextMenu',
            function(e) {

                var $this = _menus[id].currentHover = $(this);

                // Clear hide and show timeouts.
                clearTimeout(_menus[id].show);
                clearTimeout(_menus[id].hide);

                // Clear all hover state.
                $('#' + id).find('*').removeClass(_menus[id].hoverClass);

                // Set hover state on self, direct children, ancestors and ancestor direct children.
                var $parents = $this.parents('li');
                $this.add($this.find('> *')).add($parents).add($parents.find('> *')).addClass(_menus[id].hoverClass);

                // Invoke onHover callback if set, 'this' refers to the hovered list-item.
                // Discontinue default behavior if callback returns false.
                var continueDefault = true;
                if (_menus[id].onHover) {
                    if (_menus[id].onHover.apply(this, [e, _menus[id].context]) == false) continueDefault = false;
                }

                // Continue after timeout(timeout is reset on every mouseover).
                if (!_menus[id].proceed) {
                    _menus[id].show = setTimeout(function() {
                            _menus[id].proceed = true;
                            $this.mouseover();
                        },
                        _menus[id].delay);

                    return false;
                }
                _menus[id].proceed = false;

                // Hide all sibling submenu's and deeper level submenu's.
                $this.parent().find('ul').not($this.find('> ul')).hide();

                if (!continueDefault) {
                    e.preventDefault();
                    return false;
                }

                // Default behavior.
                // =================================================== //
                // Position and fade-in submenu's.
                var $submenu = $this.find('> ul');
                if ($submenu.length != 0) {
                    var offSet = $this.offset();

                    var overflow = _overflow((offSet.left + $this.parent().width() + _menus[id].submenuLeftOffset + $submenu.width() + _menus[id].widthOverflowOffset), (offSet.top + _menus[id].submenuTopOffset + $submenu.height() + _menus[id].heightOverflowOffset),_containerElem);
                    var parentWidth = $submenu.parent().parent().width();
                    var y = offSet.top - $this.parent().offset().top;
                    $submenu.css({
                        'left': (overflow.width > 0 && !_menus[id].ignoreWidthOverflow) ? ( - parentWidth - _menus[id].submenuLeftOffset + 'px') : (parentWidth + _menus[id].submenuLeftOffset + 'px'),
                        'top': (overflow.height > 0 && !_menus[id].ignoreHeightOverflow) ? (y - overflow.height + _menus[id].submenuTopOffset) + 'px': y + _menus[id].submenuTopOffset + 'px'
                    });

                    $submenu.fadeIn(_menus[id].fadeIn);
                }
                e.stopPropagation();
            })[_menus[id].livequery ? 'livequery': 'bind']('click.fwrContextMenu touchstart.fwrContextMenu',
            function(e) {

                // Invoke onSelect callback if set, 'this' refers to the selected listitem.
                // Discontinue default behavior if callback returns false.
                if (_menus[id].onSelect) {
                    if (_menus[id].onSelect.apply(this, [e, _menus[id].context]) == false) {
                        return false;
                    } else e.preventDefault(); //选择按钮选项屏蔽其他默认行为
                }

                // Default behavior.
                //====================================================//
                // Reset menu
                _resetMenu();

                // Clear active state from this context.
                $(_menus[id].context).removeClass(_global.activeClass);

                e.stopPropagation();
            });

        // Determine the event type used to invoke the menu.
        // Event type is a namespaced event so it can be easily unbound later.
        var div = document.createElement('div');
        div.setAttribute('oncontextmenu', '');
        var eventType = _menus[id].event;
        if (!eventType) {
            eventType = (typeof div.oncontextmenu != 'undefined') ? 'contextmenu.fwrContextMenu': _menus[id].operaEvent + '.fwrContextMenu';
        } else {
            eventType += '.fwrContextMenu';
        }

        // Searching for the modifier in the event type
        // (e.g. ctrl+click, shift+contextmenu)
        if (eventType.indexOf('+') != -1) {
            var chunks = eventType.split('+', 2);
            _menus[id].modifier = chunks[0] + 'Key';
            eventType = chunks[1];
        }

        // Add menu invocation handler to the context.
        return this[_menus[id].livequery ? 'livequery': 'bind'](eventType,
            function(e, touchEvent) {
                // Check for the modifier if any.
                if (typeof _menus[id].modifier == 'string' && !e[_menus[id].modifier]) return;
                if (typeof e.pageX === 'undefined') e = touchEvent;
                // Save context(i.e. the current area to which the menu belongs).
                _menus[id].context = this;
                var $menu = $('#' + id);

                // Determine start position.
                var startLeft, startTop;
                if (_menus[id].openBelowContext) {
                    var contextOffset = $(this).offset();
                    startLeft = contextOffset.left;
                    startTop = contextOffset.top + $(this).outerHeight();
                } else {
                    startLeft = e.pageX;
                    startTop = e.pageY;
                }
                startLeft += _menus[id].startLeftOffset;
                startTop += _menus[id].startTopOffset;

                // Check for overflow and correct menu-position accordingly.
                var overflow = _overflow((startLeft + $menu.width() + _menus[id].widthOverflowOffset), (startTop + $menu.height() + _menus[id].heightOverflowOffset),_containerElem);
                if (!_menus[id].ignoreWidthOverflow && overflow.width > 0) startLeft -= overflow.width;
                // Ignore y-overflow if openBelowContext or if _menus[id].ignoreHeightOverflow
                if (!_menus[id].openBelowContext && !_menus[id].ignoreHeightOverflow && overflow.height > 0) {
                    startTop -= overflow.height;
                }

                // Invoke onShow callback if set, 'this' refers to the menu.
                // Discontinue default behavior if callback returns false.
                if (_menus[id].onShow) {
                    if (_menus[id].onShow.apply($menu, [e, _menus[id].context, startLeft, startTop]) == false) {
                        return false;
                    }
                }

                // Default behavior.
                // =================================================== //
                // Reset last active menu.
                _resetMenu();

                // Set this id as active menu id.
                _global.activeId = id;

                // Hide current menu and all submenus, on first page load this is neccesary for proper keyboard support.
                $('#' + _global.activeId).add('#' + _global.activeId + ' ul').hide();

                // Clear all active context on page.
                _clearActive();

                // Make this context active.
                $(_menus[id].context).addClass(_global.activeClass);

                // Clear all hover state.
                $menu.find('li, li > *').removeClass(_menus[id].hoverClass);

                // Auto add/delete submenu arrows(spans) if set by options.
                if (_menus[id].autoAddSubmenuArrows) {
                    $menu.find('li:has(ul)').not(':has(span.' + _menus[id].submenuClass + ')').prepend('<span class="' + _menus[id].submenuClass + '"></span>');
                    $menu.find('li').not(':has(ul)').find('> span.' + _menus[id].submenuClass).remove();
                }

                // Fade-in menu at clicked-position.
                $menu.css({
                    'left': startLeft + 'px',
                    'top': startTop + 'px'
                }).fadeIn(_menus[id].fadeIn);

                // If openBelowContext, maintain contextmenu left position on window resize event.
                if (_menus[id].openBelowContext) {
                    $(window).on('resize.fwrContextMenu',
                        function() {
                            $('#' + id).css('left', $(_menus[id].context).offset().left + _menus[id].startLeftOffset + 'px');
                        });
                }

                // Bind mouseover, keyup/keydown and click events to the document.
                $(document).on('mouseover.fwrContextMenu',
                    function(e) {
                        // Remove hovers from last-opened submenu and hide any open relatedTarget submenu's after timeout.
                        if ($(e.relatedTarget).parents('#' + id).length > 0) {
                            // Clear show submenu timeout.
                            clearTimeout(_menus[id].show);

                            var $li = $(e.relatedTarget).parent().find('li');
                            $li.add($li.find('> *')).removeClass(_menus[id].hoverClass);

                            // Clear last hovered menu-item.
                            _menus[_global.activeId].currentHover = null;

                            // Set hide submenu timeout.
                            _menus[id].hide = setTimeout(function() {
                                    $li.find('ul').hide();
                                    if (_menus[id].autoHide) _globalHide(e);
                                },
                                _menus[id].delay);
                        }
                    }).on('click.fwrContextMenu touchstart.fwrContextMenu',
                    function(e) {
                        if (!_globalfwrContextMenuIgnoreHide) {
                            _globalHide(e);
                        }
                        _globalfwrContextMenuIgnoreHide = false;
                    });

                if (_menus[id].keyboard) {
                    $(document).on('keydown.fwrContextMenu',
                        function(e) {
                            switch (e.which) {
                                case 38:
                                    //keyup
                                    if (_global.keyUpDownStop) return false;
                                    _onKeyUpDown();
                                    _global.keyUpDown = setInterval(_onKeyUpDown, _menus[_global.activeId].keyDelay);
                                    _global.keyUpDownStop = true;
                                    return false;
                                case 39:
                                    //keyright
                                    if (_menus[_global.activeId].currentHover) {
                                        _menus[_global.activeId].currentHover.find('ul:visible:first li:visible:first').mouseover();
                                    } else {
                                        var visibleMenus = $('#' + _global.activeId + ', #' + _global.activeId + ' ul:visible');
                                        if (visibleMenus.length > 0) {
                                            $(visibleMenus[visibleMenus.length - 1]).find(':visible:first').mouseover();
                                        }
                                    }
                                    return false;
                                case 40:
                                    //keydown
                                    if (_global.keyUpDownStop) return false;
                                    _onKeyUpDown(true);
                                    _global.keyUpDown = setInterval(function() {
                                            _onKeyUpDown(true);
                                        },
                                        _menus[_global.activeId].keyDelay);
                                    _global.keyUpDownStop = true;
                                    return false;
                                case 37:
                                    //keyleft
                                    if (_menus[_global.activeId].currentHover) {
                                        $(_menus[_global.activeId].currentHover.parents('li')[0]).mouseover();
                                    } else {
                                        var hoveredLi = $('#' + _global.activeId + ' li.' + _menus[_global.activeId].hoverClass);
                                        if (hoveredLi.length > 0) $(hoveredLi[hoveredLi.length - 1]).mouseover();
                                    }
                                    return false;
                                case 13:
                                    //enter
                                    if (_menus[_global.activeId].currentHover) {
                                        _menus[_global.activeId].currentHover.click();
                                    } else {
                                        _globalHide(e);
                                    }
                                    break;
                                case 27:
                                    //escape
                                    _globalHide(e);
                                    break;
                                default:
                                    break;
                            }
                        }).on('keyup.fwrContextMenu',
                        function(e) {
                            clearInterval(_global.keyUpDown);
                            _global.keyUpDownStop = false;
                        });
                }

                return false;
            });
    };

    // Unbind context from context menu.
    $.fn.nofwrContextMenu = function() {
        this.off('.fwrContextMenu');
    };
    $.fn.hidden = function() {
        _globalHide();
    }
})(jQuery);

/*!
 * fwrJScrollPane - v2.0.0beta11 - 2011-07-04
 * http://fwrJScrollPane.kelvinluck.com/
 *
 * Copyright (c) 2010 Kelvin Luck
 * Dual licensed under the MIT and GPL licenses.
 */

// Script: fwrJScrollPane - cross browser customisable scrollbars
//
// *Version: 2.0.0beta11, Last updated: 2011-07-04*
//
// Project Home - http://fwrJScrollPane.kelvinluck.com/
// GitHub       - http://github.com/vitch/fwrJScrollPane
// Source       - http://github.com/vitch/fwrJScrollPane/raw/master/script/jquery.fwrJScrollPane.js
// (Minified)   - http://github.com/vitch/fwrJScrollPane/raw/master/script/jquery.fwrJScrollPane.min.js
//
// About: License
//
// Copyright (c) 2011 Kelvin Luck
// Dual licensed under the MIT or GPL Version 2 licenses.
// http://fwrJScrollPane.kelvinluck.com/MIT-LICENSE.txt
// http://fwrJScrollPane.kelvinluck.com/GPL-LICENSE.txt
//
// About: Examples
//
// All examples and demos are available through the fwrJScrollPane example site at:
// http://fwrJScrollPane.kelvinluck.com/
//
// About: Support and Testing
//
// This plugin is tested on the browsers below and has been found to work reliably on them. If you run
// into a problem on one of the supported browsers then please visit the support section on the fwrJScrollPane
// website (http://fwrJScrollPane.kelvinluck.com/) for more information on getting support. You are also
// welcome to fork the project on GitHub if you can contribute a fix for a given issue.
//
// jQuery Versions - tested in 1.4.2+ - reported to work in 1.3.x
// Browsers Tested - Firefox 3.6.8, Safari 5, Opera 10.6, Chrome 5.0, IE 6, 7, 8
//
// About: Release History
//
// 2.0.0beta11 - (in progress)
// 2.0.0beta10 - (2011-04-17) cleaner required size calculation, improved keyboard support, stickToBottom/Left, other small fixes
// 2.0.0beta9 - (2011-01-31) new API methods, bug fixes and correct keyboard support for FF/OSX
// 2.0.0beta8 - (2011-01-29) touchscreen support, improved keyboard support
// 2.0.0beta7 - (2011-01-23) scroll speed consistent (thanks Aivo Paas)
// 2.0.0beta6 - (2010-12-07) scrollToElement horizontal support
// 2.0.0beta5 - (2010-10-18) jQuery 1.4.3 support, various bug fixes
// 2.0.0beta4 - (2010-09-17) clickOnTrack support, bug fixes
// 2.0.0beta3 - (2010-08-27) Horizontal fwrMouseWheel, mwheelIntent, keyboard support, bug fixes
// 2.0.0beta2 - (2010-08-21) Bug fixes
// 2.0.0beta1 - (2010-08-17) Rewrite to follow modern best practices and enable horizontal scrolling, initially hidden
//							 elements and dynamically sized elements.
// 1.x - (2006-12-31 - 2010-07-31) Initial version, hosted at googlecode, deprecated
(function($, window, undefined) {
    $.fn.fwrJScrollPane = function(settings) {
        function fwrJScrollPane(elem, s) {
            var settings, jsp = this,
                pane, paneWidth, paneHeight, container, contentWidth, contentHeight, percentInViewH, percentInViewV,
                isScrollableV, isScrollableH, verticalDrag, dragMaxY, verticalDragPosition,
                horizontalDrag, dragMaxX, horizontalDragPosition, verticalBar, verticalTrack, scrollbarWidth,
                verticalTrackHeight, verticalDragHeight, arrowUp, arrowDown, horizontalBar, horizontalTrack,
                horizontalTrackWidth, horizontalDragWidth, arrowLeft, arrowRight, reinitialiseInterval, originalPadding,
                originalPaddingTotalWidth, previousContentWidth, wasAtTop = true,
                wasAtLeft = true,
                wasAtBottom = false,
                wasAtRight = false,
                originalElement = elem.clone(false, false).empty(),
                mwEvent = $.fn.mwheelIntent ? 'mwheelIntent.jsp': 'mousewheel.jsp';
            originalPadding = elem.css('paddingTop') + ' ' + elem.css('paddingRight') + ' ' + elem.css('paddingBottom') + ' ' + elem.css('paddingLeft');
            originalPaddingTotalWidth = (parseInt(elem.css('paddingLeft'), 10) || 0) + (parseInt(elem.css('paddingRight'), 10) || 0);
            function initialise(s) {
                var isMaintainingPositon, lastContentX, lastContentY, hasContainingSpaceChanged, originalScrollTop, originalScrollLeft, maintainAtBottom = false,
                    maintainAtRight = false;
                settings = s;
                if (pane === undefined) {
                    originalScrollTop = elem.scrollTop();
                    originalScrollLeft = elem.scrollLeft();
                    elem.css({
                        overflow: 'hidden',
                        padding: 0
                    });
                    paneWidth = elem.innerWidth() + originalPaddingTotalWidth;
                    paneHeight = elem.innerHeight();
                    elem.width(paneWidth);
                    pane = $('<div class="fwrJspPane" />').css('padding', originalPadding).append(elem.children());
                    container = $('<div class="fwrJspContainer" />').css({
                        'width': paneWidth + 'px',
                        'height': paneHeight + 'px'
                    }).append(pane).appendTo(elem);
                } else {
                    maintainAtBottom = settings.stickToBottom && isCloseToBottom();
                    maintainAtRight = settings.stickToRight && isCloseToRight();
                    hasContainingSpaceChanged = elem.innerWidth() + originalPaddingTotalWidth != paneWidth || elem.outerHeight() != paneHeight;
                    if (hasContainingSpaceChanged) {
                        paneWidth = elem.innerWidth() + originalPaddingTotalWidth;
                        paneHeight = elem.innerHeight();
                        container.css({
                            width: paneWidth + 'px',
                            height: paneHeight + 'px'
                        });
                    }
                    if (!hasContainingSpaceChanged && previousContentWidth == contentWidth && pane.outerHeight() == contentHeight) {
                        elem.width(paneWidth);
                        return;
                    }
                    previousContentWidth = contentWidth;
                    pane.css('width', '');
                    elem.width(paneWidth);
                    container.find('>.fwrJspVerticalBar,>.fwrJspHorizontalBar').remove().end();
                }
                pane.css('overflow', 'auto');
                if (s.contentWidth) {
                    contentWidth = s.contentWidth;
                } else {
                    contentWidth = pane[0].scrollWidth;
                }
                contentHeight = pane[0].scrollHeight;
                pane.css('overflow', '');
                percentInViewH = contentWidth / paneWidth;
                percentInViewV = contentHeight / paneHeight;
                isScrollableV = percentInViewV > 1;
                isScrollableH = percentInViewH > 1;
                if (! (isScrollableH || isScrollableV)) {
                    elem.removeClass('jspScrollable');
                    pane.css({
                        top: 0,
                        width: container.width() - originalPaddingTotalWidth
                    });
                    removeMousewheel();
                    removeFocusHandler();
                    removeKeyboardNav();
                    removeClickOnTrack();
                } else {
                    elem.addClass('jspScrollable');
                    isMaintainingPositon = settings.maintainPosition && (verticalDragPosition || horizontalDragPosition);
                    if (isMaintainingPositon) {
                        lastContentX = contentPositionX();
                        lastContentY = contentPositionY();
                    }
                    initialiseVerticalScroll();
                    initialiseHorizontalScroll();
                    resizeScrollbars();
                    if (isMaintainingPositon) {
                        scrollToX(maintainAtRight ? (contentWidth - paneWidth) : lastContentX, false);
                        scrollToY(maintainAtBottom ? (contentHeight - paneHeight) : lastContentY, false);
                    }
                    initFocusHandler();
                    initMousewheel();
                    initTouch();
                    if (settings.enableKeyboardNavigation) {
                        initKeyboardNav();
                    }
                    if (settings.clickOnTrack) {
                        initClickOnTrack();
                    }
                    observeHash();
                    if (settings.hijackInternalLinks) {
                        hijackInternalLinks();
                    }
                }
                if (settings.autoReinitialise && !reinitialiseInterval) {
                    reinitialiseInterval = setInterval(function() {
                            initialise(settings);
                        },
                        settings.autoReinitialiseDelay);
                } else if (!settings.autoReinitialise && reinitialiseInterval) {
                    clearInterval(reinitialiseInterval);
                }
                originalScrollTop && elem.scrollTop(0) && scrollToY(originalScrollTop, false);
                originalScrollLeft && elem.scrollLeft(0) && scrollToX(originalScrollLeft, false);
                elem.trigger('jsp-initialised', [isScrollableH || isScrollableV]);
            }
            function initialiseVerticalScroll() {
                if (isScrollableV) {
                    container.append($('<div class="fwrJspVerticalBar" />').append($('<div class="fwrJspCap fwrJspCapTop" />'), $('<div class="fwrJspTrack" />').append($('<div class="fwrJspDrag" />').append($('<div class="fwrJspDragTop" />'), $('<div class="fwrJspDragBottom" />'))), $('<div class="fwrJspCap fwrJspCapBottom" />')));
                    verticalBar = container.find('>.fwrJspVerticalBar');
                    verticalTrack = verticalBar.find('>.fwrJspTrack');
                    verticalDrag = verticalTrack.find('>.fwrJspDrag');
                    if (settings.showArrows) {
                        arrowUp = $('<a class="fwrJspArrow fwrJspArrowUp" />').on('mousedown.jsp', getArrowScroll(0, -1)).on('click.jsp', nil);
                        arrowDown = $('<a class="fwrJspArrow fwrJspArrowDown" />').on('mousedown.jsp', getArrowScroll(0, 1)).on('click.jsp', nil);
                        if (settings.arrowScrollOnHover) {
                            arrowUp.on('mouseover.jsp', getArrowScroll(0, -1, arrowUp));
                            arrowDown.on('mouseover.jsp', getArrowScroll(0, 1, arrowDown));
                        }
                        appendArrows(verticalTrack, settings.verticalArrowPositions, arrowUp, arrowDown);
                    }
                    verticalTrackHeight = paneHeight;
                    container.find('>.fwrJspVerticalBar>.fwrJspCap:visible,>.fwrJspVerticalBar>.fwrJspArrow').each(function() {
                        verticalTrackHeight -= $(this).outerHeight();
                    });
                    verticalDrag.hover(function() {
                            verticalDrag.addClass('jspHover');
                        },
                        function() {
                            verticalDrag.removeClass('jspHover');
                        }).on('mousedown.jsp',
                        function(e) {
                            $('html').on('dragstart.jsp selectstart.jsp', nil);
                            verticalDrag.addClass('jspActive');
                            var startY = e.pageY - verticalDrag.position().top;
                            $('html').on('mousemove.jsp',
                                function(e) {
                                    positionDragY(e.pageY - startY, false);
                                }).on('mouseup.jsp mouseleave.jsp', cancelDrag);
                            return false;
                        });
                    sizeVerticalScrollbar();
                }
            }
            function sizeVerticalScrollbar() {
                verticalTrack.height(verticalTrackHeight + 'px');
                verticalDragPosition = 0;
                scrollbarWidth = settings.verticalGutter + verticalTrack.outerWidth();
                pane.width(paneWidth - scrollbarWidth - originalPaddingTotalWidth);
                try {
                    if (verticalBar.position().left === 0) {
                        pane.css('margin-left', scrollbarWidth + 'px');
                    }
                } catch(err) {}
            }
            function initialiseHorizontalScroll() {
                if (settings.disableHorizontalScroll) return;
                if (isScrollableH) {
                    container.append($('<div class="fwrJspHorizontalBar" />').append($('<div class="fwrJspCap fwrJspCapLeft" />'), $('<div class="fwrJspTrack" />').append($('<div class="fwrJspDrag" />').append($('<div class="fwrJspDragLeft" />'), $('<div class="fwrJspDragRight" />'))), $('<div class="fwrJspCap fwrJspCapRight" />')));
                    horizontalBar = container.find('>.fwrJspHorizontalBar');
                    horizontalTrack = horizontalBar.find('>.fwrJspTrack');
                    horizontalDrag = horizontalTrack.find('>.fwrJspDrag');
                    if (settings.showArrows) {
                        arrowLeft = $('<a class="fwrJspArrow fwrJspArrowLeft" />').on('mousedown.jsp', getArrowScroll( - 1, 0)).on('click.jsp', nil);
                        arrowRight = $('<a class="fwrJspArrow fwrJspArrowRight" />').on('mousedown.jsp', getArrowScroll(1, 0)).on('click.jsp', nil);
                        if (settings.arrowScrollOnHover) {
                            arrowLeft.on('mouseover.jsp', getArrowScroll( - 1, 0, arrowLeft));
                            arrowRight.on('mouseover.jsp', getArrowScroll(1, 0, arrowRight));
                        }
                        appendArrows(horizontalTrack, settings.horizontalArrowPositions, arrowLeft, arrowRight);
                    }
                    horizontalDrag.hover(function() {
                            horizontalDrag.addClass('jspHover');
                        },
                        function() {
                            horizontalDrag.removeClass('jspHover');
                        }).on('mousedown.jsp',
                        function(e) {
                            $('html').on('dragstart.jsp selectstart.jsp', nil);
                            horizontalDrag.addClass('jspActive');
                            var startX = e.pageX - horizontalDrag.position().left;
                            $('html').on('mousemove.jsp',
                                function(e) {
                                    positionDragX(e.pageX - startX, false);
                                }).on('mouseup.jsp mouseleave.jsp', cancelDrag);
                            return false;
                        });
                    horizontalTrackWidth = container.innerWidth();
                    sizeHorizontalScrollbar();
                }
            }
            function sizeHorizontalScrollbar() {
                container.find('>.fwrJspHorizontalBar>.fwrJspCap:visible,>.fwrJspHorizontalBar>.fwrJspArrow').each(function() {
                    horizontalTrackWidth -= $(this).outerWidth();
                });
                horizontalTrack.width(horizontalTrackWidth + 'px');
                horizontalDragPosition = 0;
            }
            function resizeScrollbars() {
                if (settings.disableHorizontalScroll) isScrollableH = false;
                if (isScrollableH && isScrollableV) {
                    var horizontalTrackHeight = horizontalTrack.outerHeight(),
                        verticalTrackWidth = verticalTrack.outerWidth();
                    verticalTrackHeight -= horizontalTrackHeight;
                    $(horizontalBar).find('>.fwrJspCap:visible,>.fwrJspArrow').each(function() {
                        horizontalTrackWidth += $(this).outerWidth();
                    });
                    horizontalTrackWidth -= verticalTrackWidth;
                    paneHeight -= verticalTrackWidth;
                    paneWidth -= horizontalTrackHeight;
                    horizontalTrack.parent().append($('<div class="fwrJspCorner" />').css('width', horizontalTrackHeight + 'px'));
                    sizeVerticalScrollbar();
                    sizeHorizontalScrollbar();
                }
                if (isScrollableH) {
                    pane.width((container.outerWidth() - originalPaddingTotalWidth) + 'px');
                }
                contentHeight = pane.outerHeight();
                percentInViewV = contentHeight / paneHeight;
                if (isScrollableH) {
                    horizontalDragWidth = Math.ceil(1 / percentInViewH * horizontalTrackWidth);
                    if (horizontalDragWidth > settings.horizontalDragMaxWidth) {
                        horizontalDragWidth = settings.horizontalDragMaxWidth;
                    } else if (horizontalDragWidth < settings.horizontalDragMinWidth) {
                        horizontalDragWidth = settings.horizontalDragMinWidth;
                    }
                    horizontalDrag.width(horizontalDragWidth + 'px');
                    dragMaxX = horizontalTrackWidth - horizontalDragWidth;
                    _positionDragX(horizontalDragPosition);
                }
                if (isScrollableV) {
                    verticalDragHeight = Math.ceil(1 / percentInViewV * verticalTrackHeight);
                    if (verticalDragHeight > settings.verticalDragMaxHeight) {
                        verticalDragHeight = settings.verticalDragMaxHeight;
                    } else if (verticalDragHeight < settings.verticalDragMinHeight) {
                        verticalDragHeight = settings.verticalDragMinHeight;
                    }
                    verticalDrag.height(verticalDragHeight + 'px');
                    dragMaxY = verticalTrackHeight - verticalDragHeight;
                    _positionDragY(verticalDragPosition);
                }
            }
            function appendArrows(ele, p, a1, a2) {
                var p1 = "before",
                    p2 = "after",
                    aTemp;
                if (p == "os") {
                    p = /Mac/.test(navigator.platform) ? "after": "split";
                }
                if (p == p1) {
                    p2 = p;
                } else if (p == p2) {
                    p1 = p;
                    aTemp = a1;
                    a1 = a2;
                    a2 = aTemp;
                }
                ele[p1](a1)[p2](a2);
            }
            function getArrowScroll(dirX, dirY, ele) {
                return function() {
                    arrowScroll(dirX, dirY, this, ele);
                    this.blur();
                    return false;
                };
            }
            function arrowScroll(dirX, dirY, arrow, ele) {
                arrow = $(arrow).addClass('jspActive');
                var eve, scrollTimeout, isFirst = true,
                    doScroll = function() {
                        if (dirX !== 0) {
                            jsp.scrollByX(dirX * settings.arrowButtonSpeed);
                        }
                        if (dirY !== 0) {
                            jsp.scrollByY(dirY * settings.arrowButtonSpeed);
                        }
                        scrollTimeout = setTimeout(doScroll, isFirst ? settings.initialDelay: settings.arrowRepeatFreq);
                        isFirst = false;
                    };
                doScroll();
                eve = ele ? 'mouseout.jsp': 'mouseup.jsp';
                ele = ele || $('html');
                ele.on(eve,
                    function() {
                        arrow.removeClass('jspActive');
                        scrollTimeout && clearTimeout(scrollTimeout);
                        scrollTimeout = null;
                        ele.off(eve);
                    });
            }
            function initClickOnTrack() {
                removeClickOnTrack();
                if (isScrollableV) {
                    var bindFunctionV = function(e, isIE, trackObj) {
                        if (e.originalTarget === undefined || e.originalTarget == e.currentTarget) {
                            var clickedTrack = $(this);
                            if (trackObj != null) {
                                clickedTrack = trackObj
                            }
                            var offset = clickedTrack.offset(),
                                direction = e.pageY - offset.top - verticalDragPosition,
                                scrollTimeout,
                                isFirst = true,
                                doScroll = function() {
                                    var offset = clickedTrack.offset(),
                                        pos = e.pageY - offset.top - verticalDragHeight / 2,
                                        contentDragY = paneHeight * settings.scrollPagePercent,
                                        dragY = dragMaxY * contentDragY / (contentHeight - paneHeight);
                                    if (direction < 0) {
                                        if (verticalDragPosition - dragY > pos) {
                                            jsp.scrollByY( - contentDragY)
                                        } else {
                                            positionDragY(pos)
                                        }
                                    } else if (direction > 0) {
                                        if (verticalDragPosition + dragY < pos) {
                                            jsp.scrollByY(contentDragY)
                                        } else {
                                            positionDragY(pos)
                                        }
                                    } else {
                                        cancelClick();
                                        return
                                    }
                                    if (isIE == null || isIE == false) scrollTimeout = setTimeout(doScroll, isFirst ? settings.initialDelay: settings.trackClickRepeatFreq);
                                    isFirst = false
                                },
                                cancelClick = function() {
                                    scrollTimeout && clearTimeout(scrollTimeout);
                                    scrollTimeout = null;
                                    $(document).off('mouseup.jsp', cancelClick)
                                };
                            doScroll();
                            $(document).on('mouseup.jsp', cancelClick);
                            return false
                        }
                    };
                    var bindFunctionV2 = function(e) {
                        bindFunctionV(e, true, $(this));
                    }
                    var agent = navigator.userAgent.toLowerCase();
                    if (/msie/.test(agent) && !/opera/.test(agent)) {
                        var version = parseFloat(agent.match(/msie (\d+)/)[1]);
                        var isIE7 = ((version == 7 && !document.documentMode) || document.documentMode == 7);
                        var isIE8 = document.documentMode == 8;
                        if (isIE7 || isIE8) verticalTrack.on('dblclick', bindFunctionV2);
                    }
                    verticalTrack.on('mousedown.jsp', bindFunctionV);
                }
                if (isScrollableH) {
                    var bindFunction = function(e, isIE, trackObj) {
                        if (e.originalTarget === undefined || e.originalTarget == e.currentTarget) {
                            var clickedTrack = $(this);
                            if (trackObj != null) {
                                clickedTrack = trackObj
                            }
                            var offset = clickedTrack.offset(),
                                direction = e.pageX - offset.left - horizontalDragPosition,
                                scrollTimeout,
                                isFirst = true,
                                doScroll = function() {
                                    var offset = clickedTrack.offset(),
                                        pos = e.pageX - offset.left - horizontalDragWidth / 2,
                                        contentDragX = paneWidth * settings.scrollPagePercent,
                                        dragX = dragMaxX * contentDragX / (contentWidth - paneWidth);
                                    if (direction < 0) {
                                        if (horizontalDragPosition - dragX > pos) {
                                            jsp.scrollByX( - contentDragX)
                                        } else {
                                            positionDragX(pos)
                                        }
                                    } else if (direction > 0) {
                                        if (horizontalDragPosition + dragX < pos) {
                                            jsp.scrollByX(contentDragX)
                                        } else {
                                            positionDragX(pos)
                                        }
                                    } else {
                                        cancelClick();
                                        return
                                    }
                                    if (isIE == null || isIE == false) scrollTimeout = setTimeout(doScroll, isFirst ? settings.initialDelay: settings.trackClickRepeatFreq);
                                    isFirst = false
                                },
                                cancelClick = function() {
                                    scrollTimeout && clearTimeout(scrollTimeout);
                                    scrollTimeout = null;
                                    $(document).off('mouseup.jsp', cancelClick)
                                };
                            doScroll();
                            $(document).on('mouseup.jsp', cancelClick);
                            return false
                        }
                    };
                    var bindFunction2 = function(e) {
                        bindFunction(e, true, $(this));
                    };
                    var agent = navigator.userAgent.toLowerCase();
                    if (/msie/.test(agent) && !/opera/.test(agent)) {
                        var version = parseFloat(agent.match(/msie (\d+)/)[1]);
                        var isIE7 = ((version == 7 && !document.documentMode) || document.documentMode == 7);
                        var isIE8 = document.documentMode == 8;
                        if (isIE7 || isIE8) {
                            horizontalTrack.on('dblclick', bindFunction2);
                        }
                    };
                    horizontalTrack.on('mousedown.jsp', bindFunction);
                }
            }
            function removeClickOnTrack() {
                if (horizontalTrack) {
                    horizontalTrack.off('mousedown.jsp');
                }
                if (verticalTrack) {
                    verticalTrack.off('mousedown.jsp');
                }
            }
            function cancelDrag() {
                $('html').off('dragstart.jsp selectstart.jsp mousemove.jsp mouseup.jsp mouseleave.jsp');
                if (verticalDrag) {
                    verticalDrag.removeClass('jspActive');
                }
                if (horizontalDrag) {
                    horizontalDrag.removeClass('jspActive');
                }
            }
            function positionDragY(destY, animate) {
                if (!isScrollableV) {
                    return;
                }
                if (destY < 0) {
                    destY = 0;
                } else if (destY > dragMaxY) {
                    destY = dragMaxY;
                }
                if (animate === undefined) {
                    animate = settings.animateScroll;
                }
                if (animate) {
                    jsp.animate(verticalDrag, 'top', destY, _positionDragY);
                } else {
                    verticalDrag.css('top', destY);
                    _positionDragY(destY);
                }
            }
            function _positionDragY(destY) {
                if (destY === undefined) {
                    destY = verticalDrag.position().top;
                }
                container.scrollTop(0);
                verticalDragPosition = destY;
                var isAtTop = verticalDragPosition === 0,
                    isAtBottom = verticalDragPosition == dragMaxY;
                var percentScrolled = 1;
                if (dragMaxY != 0) percentScrolled = destY / dragMaxY;
                var destTop = -percentScrolled * (contentHeight - paneHeight);
                if (wasAtTop != isAtTop || wasAtBottom != isAtBottom) {
                    wasAtTop = isAtTop;
                    wasAtBottom = isAtBottom;
                    elem.trigger('jsp-arrow-change', [wasAtTop, wasAtBottom, wasAtLeft, wasAtRight]);
                }
                updateVerticalArrows(isAtTop, isAtBottom);
                pane.css('top', destTop);
                elem.trigger('jsp-scroll-y', [ - destTop, isAtTop, isAtBottom]).trigger('scroll');
            }
            function positionDragX(destX, animate) {
                if (!isScrollableH) {
                    return;
                }
                if (destX < 0) {
                    destX = 0;
                } else if (destX > dragMaxX) {
                    destX = dragMaxX;
                }
                if (animate === undefined) {
                    animate = settings.animateScroll;
                }
                if (animate) {
                    jsp.animate(horizontalDrag, 'left', destX, _positionDragX);
                } else {
                    horizontalDrag.css('left', destX);
                    _positionDragX(destX);
                }
            }
            function _positionDragX(destX) {
                if (destX === undefined) {
                    destX = horizontalDrag.position().left;
                }
                container.scrollTop(0);
                horizontalDragPosition = destX;
                var isAtLeft = horizontalDragPosition === 0,
                    isAtRight = horizontalDragPosition == dragMaxX;
                var percentScrolled = 1;
                if (dragMaxX != 0) percentScrolled = destX / dragMaxX;
                var destLeft = -percentScrolled * (contentWidth - paneWidth);
                if (wasAtLeft != isAtLeft || wasAtRight != isAtRight) {
                    wasAtLeft = isAtLeft;
                    wasAtRight = isAtRight;
                    elem.trigger('jsp-arrow-change', [wasAtTop, wasAtBottom, wasAtLeft, wasAtRight]);
                }
                updateHorizontalArrows(isAtLeft, isAtRight);
                pane.css('left', destLeft);
                elem.trigger('jsp-scroll-x', [ - destLeft, isAtLeft, isAtRight]).trigger('scroll');
            }
            function updateVerticalArrows(isAtTop, isAtBottom) {
                if (settings.showArrows) {
                    arrowUp[isAtTop ? 'addClass': 'removeClass']('jspDisabled');
                    arrowDown[isAtBottom ? 'addClass': 'removeClass']('jspDisabled');
                }
            }
            function updateHorizontalArrows(isAtLeft, isAtRight) {
                if (settings.showArrows) {
                    arrowLeft[isAtLeft ? 'addClass': 'removeClass']('jspDisabled');
                    arrowRight[isAtRight ? 'addClass': 'removeClass']('jspDisabled');
                }
            }
            function scrollToY(destY, animate) {
                var percentScrolled = destY / (contentHeight - paneHeight);
                positionDragY(percentScrolled * dragMaxY, animate);
            }
            function scrollToX(destX, animate) {
                var percentScrolled = destX / (contentWidth - paneWidth);
                positionDragX(percentScrolled * dragMaxX, animate);
            }
            function scrollToElement(ele, stickToTop, animate) {
                var e, eleHeight, eleWidth, eleTop = 0,
                    eleLeft = 0,
                    viewportTop, viewportLeft, maxVisibleEleTop, maxVisibleEleLeft, destY, destX;
                var nDeltaOffsetY = arguments[3] ? arguments[3] : 0;
                try {
                    e = $(ele);
                } catch(err) {
                    return;
                }
                eleHeight = e.outerHeight();
                eleWidth = e.outerWidth();
                container.scrollTop(0);
                container.scrollLeft(0);
                while (!e.is('.fwrJspPane')) {
                    eleTop += e.position().top;
                    eleLeft += e.position().left;
                    e = e.offsetParent();
                    if (/^body|html$/i.test(e[0].nodeName)) {
                        return;
                    }
                }
                viewportTop = contentPositionY();
                maxVisibleEleTop = viewportTop + paneHeight;
                if (eleTop < viewportTop || stickToTop) {
                    destY = eleTop - settings.verticalGutter;
                } else if (eleTop + eleHeight > maxVisibleEleTop) {
                    destY = eleTop - paneHeight + eleHeight + settings.verticalGutter;
                }
                if (destY) {
                    scrollToY(destY + nDeltaOffsetY, animate);
                }
                viewportLeft = contentPositionX();
                maxVisibleEleLeft = viewportLeft + paneWidth;
                if (eleLeft < viewportLeft || stickToTop) {
                    destX = eleLeft - settings.horizontalGutter;
                } else if (eleLeft + eleWidth > maxVisibleEleLeft) {
                    destX = eleLeft - paneWidth + eleWidth + settings.horizontalGutter;
                }
                if (destX) {
                    scrollToX(destX, animate);
                }
            }
            function contentPositionX() {
                return - pane.position().left;
            }
            function contentPositionY() {
                return - pane.position().top;
            }
            function isCloseToBottom() {
                var scrollableHeight = contentHeight - paneHeight;
                return (scrollableHeight > 20) && (scrollableHeight - contentPositionY() < 10);
            }
            function isCloseToRight() {
                var scrollableWidth = contentWidth - paneWidth;
                return (scrollableWidth > 20) && (scrollableWidth - contentPositionX() < 10);
            }
            function initMousewheel() {
                container.off(mwEvent).on(mwEvent,
                    function(event, delta, deltaX, deltaY) {
                        var targetType = $(event.target).attr("type") ? ($(event.target).attr("type")) : event.target.type;
                        if (targetType) {targetType = targetType.toLowerCase()}
                        if (targetType == 'text' || targetType == 'textarea' || event.target.isContentEditable) return true;
                        var dX = horizontalDragPosition,
                            dY = verticalDragPosition;
                        jsp.scrollBy(deltaX * settings.mouseWheelSpeed, -deltaY * settings.mouseWheelSpeed, false);
                        return dX == horizontalDragPosition && dY == verticalDragPosition;
                    });
            }
            function removeMousewheel() {
                container.off(mwEvent);
            }
            function nil() {
                return false;
            }
            function initFocusHandler() {
                pane.find(':input,a').off('focus.jsp').on('focus.jsp',
                    function(e) {
                        scrollToElement(e.target, false);
                    });
            }
            function removeFocusHandler() {
                pane.find(':input,a').off('focus.jsp');
            }
            function initKeyboardNav() {
                var keyDown, elementHasScrolled, validParents = [];
                isScrollableH && validParents.push(horizontalBar[0]);
                isScrollableV && validParents.push(verticalBar[0]);
                pane.focus(function() {
                    elem.focus();
                });
                elem.attr('tabindex', 0).off('keydown.jsp keypress.jsp').on('keydown.jsp',
                    function(e) {
                        var targetType = $(e.target).attr("type") ? ($(e.target).attr("type")) : e.target.type;
                        if (targetType) {targetType = targetType.toLowerCase()}
                        if (targetType == 'text' || targetType == 'textarea' || e.target.isContentEditable) return true;

                        var dX = horizontalDragPosition,
                            dY = verticalDragPosition;
                        switch (e.keyCode) {
                            case 40:
                            case 38:
                            case 32:
                                keyDown = e.keyCode;
                                keyDownHandler();
                                break;
                            case 34:
                            case 33:
                            case 39:
                            case 37:
                            case 35:
                            case 36:
                                keyDown = e.keyCode;
                                keyDownHandler();
                                keyDown = null;
                                break;
                        }
                        elementHasScrolled = e.keyCode == keyDown && dX != horizontalDragPosition || dY != verticalDragPosition;
                        return ! elementHasScrolled;
                    }).on('keypress.jsp',
                    function(e) {
                        var targetType = $(e.target).attr("type") ? ($(e.target).attr("type")) : e.target.type;
                        if (targetType) {targetType = targetType.toLowerCase()}
                        if (targetType == 'text' || targetType == 'textarea' || e.target.isContentEditable) return true;
                        if (e.keyCode == keyDown) {

                            keyDownHandler();
                        }
                        return ! elementHasScrolled;
                    });
                if (settings.hideFocus) {
                    elem.css('outline', 'none');
                    if ('hideFocus' in container[0]) {
                        elem.attr('hideFocus', true);
                    }
                } else {
                    elem.css('outline', '');
                    if ('hideFocus' in container[0]) {
                        elem.attr('hideFocus', false);
                    }
                }
                function keyDownHandler() {
                    var dX = horizontalDragPosition,
                        dY = verticalDragPosition;
                    if (settings.keyDownCallback[keyDown] != null && typeof(settings.keyDownCallback[keyDown]) == "function") {
                        settings.keyDownCallback[keyDown]();
                    } else {
                        switch (keyDown) {
                            case 40:
                                jsp.scrollByY(settings.keyboardSpeed, false);
                                break;
                            case 38:
                                jsp.scrollByY( - settings.keyboardSpeed, false);
                                break;
                            case 34:
                            case 32:
                                jsp.scrollByY(paneHeight * settings.scrollPagePercent, false);
                                break;
                            case 33:
                                jsp.scrollByY( - paneHeight * settings.scrollPagePercent, false);
                                break;
                            case 39:
                                jsp.scrollByX(settings.keyboardSpeed, false);
                                break;
                            case 37:
                                jsp.scrollByX( - settings.keyboardSpeed, false);
                                break;
                            case 35:
                                scrollToY(contentHeight - paneHeight);
                                break;
                            case 36:
                                scrollToY(0);
                                break;
                        }
                    }
                    elementHasScrolled = dX != horizontalDragPosition || dY != verticalDragPosition;
                    return elementHasScrolled;
                }
            }
            function removeKeyboardNav() {
                elem.attr('tabindex', '-1').removeAttr('tabindex').off('keydown.jsp keypress.jsp');
            }
            function observeHash() {
                if (location.hash && location.hash.length > 1) {
                    var e, retryInt, hash = escape(location.hash);
                    try {
                        e = $(hash);
                    } catch(err) {
                        return;
                    }
                    if (e.length && pane.find(hash)) {
                        if (container.scrollTop() === 0) {
                            retryInt = setInterval(function() {
                                    if (container.scrollTop() > 0) {
                                        scrollToElement(hash, true);
                                        $(document).scrollTop(container.position().top);
                                        clearInterval(retryInt);
                                    }
                                },
                                50);
                        } else {
                            scrollToElement(hash, true);
                            $(document).scrollTop(container.position().top);
                        }
                    }
                }
            }
            function unhijackInternalLinks() {
                $('a.jspHijack').off('click.jsp-hijack').removeClass('jspHijack');
            }
            function hijackInternalLinks() {
                unhijackInternalLinks();
                $('a[href^=#]').addClass('jspHijack').on('click.jsp-hijack',
                    function() {
                        var uriParts = this.href.split('#'),
                            hash;
                        if (uriParts.length > 1) {
                            hash = uriParts[1];
                            if (hash.length > 0 && pane.find('#' + hash).length > 0) {
                                scrollToElement('#' + hash, true);
                                return false;
                            }
                        }
                    });
            }
            function initTouch() {
                if (settings.initTouchScreen) {
                    var startX, startY, touchStartX, touchStartY, moved, moving = false;
                    container.off('touchstart.jsp touchmove.jsp touchend.jsp click.jsp-touchclick').on('touchstart.jsp',
                        function(e) {
                            var touch = e.originalEvent.touches[0];
                            startX = contentPositionX();
                            startY = contentPositionY();
                            touchStartX = touch.pageX;
                            touchStartY = touch.pageY;
                            moved = false;
                            moving = true;
                        }).on('touchmove.jsp',
                        function(ev) {
                            if (!moving) {
                                return;
                            }
                            var touchPos = ev.originalEvent.touches[0],
                                dX = horizontalDragPosition,
                                dY = verticalDragPosition;
                            jsp.scrollTo(startX + touchStartX - touchPos.pageX, startY + touchStartY - touchPos.pageY);
                            moved = moved || Math.abs(touchStartX - touchPos.pageX) > 5 || Math.abs(touchStartY - touchPos.pageY) > 5;
                            return dX == horizontalDragPosition && dY == verticalDragPosition;
                        }).on('touchend.jsp',
                        function(e) {
                            moving = false;
                        }).on('click.jsp-touchclick',
                        function(e) {
                            if (moved) {
                                moved = false;
                                return false;
                            }
                        });
                }
            }
            function destroy() {
                var currentY = contentPositionY(),
                    currentX = contentPositionX();
                elem.removeClass('jspScrollable').off('.jsp');
                elem.replaceWith(originalElement.append(pane.children()));
                originalElement.scrollTop(currentY);
                originalElement.scrollLeft(currentX);
            }
            $.extend(jsp, {
                reinitialise: function(s) {
                    s = $.extend({},
                        settings, s);
                    initialise(s);
                },
                scrollToElement: function(ele, stickToTop, animate) {
                    var nDeltaOffsetY = arguments[3] ? arguments[3] : 0;
                    scrollToElement(ele, stickToTop, animate, nDeltaOffsetY);
                },
                scrollTo: function(destX, destY, animate) {
                    scrollToX(destX, animate);
                    scrollToY(destY, animate);
                },
                scrollToX: function(destX, animate) {
                    scrollToX(destX, animate);
                },
                scrollToY: function(destY, animate) {
                    scrollToY(destY, animate);
                },
                scrollToPercentX: function(destPercentX, animate) {
                    scrollToX(destPercentX * (contentWidth - paneWidth), animate);
                },
                scrollToPercentY: function(destPercentY, animate) {
                    scrollToY(destPercentY * (contentHeight - paneHeight), animate);
                },
                scrollBy: function(deltaX, deltaY, animate) {
                    jsp.scrollByX(deltaX, animate);
                    jsp.scrollByY(deltaY, animate);
                },
                scrollByX: function(deltaX, animate) {
                    var destX = contentPositionX() + Math[deltaX < 0 ? 'floor': 'ceil'](deltaX),
                        percentScrolled = destX / (contentWidth - paneWidth);
                    positionDragX(percentScrolled * dragMaxX, animate);
                },
                scrollByY: function(deltaY, animate) {
                    var destY = contentPositionY() + Math[deltaY < 0 ? 'floor': 'ceil'](deltaY),
                        percentScrolled = destY / (contentHeight - paneHeight);
                    positionDragY(percentScrolled * dragMaxY, animate);
                },
                positionDragX: function(x, animate) {
                    positionDragX(x, animate);
                },
                positionDragY: function(y, animate) {
                    positionDragY(y, animate);
                },
                animate: function(ele, prop, value, stepCallback) {
                    var params = {};
                    params[prop] = value;
                    ele.animate(params, {
                        'duration': settings.animateDuration,
                        'easing': settings.animateEase,
                        'queue': false,
                        'step': stepCallback
                    });
                },
                getContentPositionX: function() {
                    return contentPositionX();
                },
                getContentPositionY: function() {
                    return contentPositionY();
                },
                getContentWidth: function() {
                    return contentWidth;
                },
                getContentHeight: function() {
                    return contentHeight;
                },
                getPercentScrolledX: function() {
                    return contentPositionX() / (contentWidth - paneWidth);
                },
                getPercentScrolledY: function() {
                    return contentPositionY() / (contentHeight - paneHeight);
                },
                getIsScrollableH: function() {
                    return isScrollableH;
                },
                getIsScrollableV: function() {
                    return isScrollableV;
                },
                getScrollBarWidth: function(){
                    return jsp.getIsScrollableV() ? (settings.verticalGutter + verticalTrack.outerWidth()) : 0;
                },
                getScrollBarHeight: function(){
                    return jsp.getIsScrollableH() ? (settings.horizontalGutter + horizontalTrack.outerHeight()) : 0;
                },
                getContentPane: function() {
                    return pane;
                },
                scrollToBottom: function(animate) {
                    positionDragY(dragMaxY, animate);
                },
                hijackInternalLinks: function() {
                    hijackInternalLinks();
                },
                destroy: function() {
                    destroy();
                }
            });
            initialise(s);
        }
        settings = $.extend({},
            $.fn.fwrJScrollPane.defaults, settings);
        $.each(['mouseWheelSpeed', 'arrowButtonSpeed', 'trackClickSpeed', 'keyboardSpeed'],
            function() {
                settings[this] = settings[this] || settings.speed;
            });
        return this.each(function() {
            var elem = $(this),
                jspApi = elem.data('jsp');
            if (jspApi) {
                jspApi.reinitialise(settings);
            } else {
                jspApi = new fwrJScrollPane(elem, settings);
                elem.data('jsp', jspApi);
            }
        });
    };
    $.fn.fwrJScrollPane.defaults = {
        disableHorizontalScroll: false,
        initTouchScreen: false,
        showArrows: false,
        maintainPosition: true,
        stickToBottom: false,
        stickToRight: false,
        clickOnTrack: true,
        autoReinitialise: false,
        autoReinitialiseDelay: 500,
        verticalDragMinHeight: 5,
        verticalDragMaxHeight: 99999,
        horizontalDragMinWidth: 0,
        horizontalDragMaxWidth: 99999,
        contentWidth: undefined,
        animateScroll: false,
        animateDuration: 300,
        animateEase: 'linear',
        hijackInternalLinks: false,
        verticalGutter: 4,
        horizontalGutter: 4,
        mouseWheelSpeed: 0,
        arrowButtonSpeed: 0,
        arrowRepeatFreq: 50,
        arrowScrollOnHover: false,
        trackClickSpeed: 0,
        trackClickRepeatFreq: 70,
        verticalArrowPositions: 'split',
        horizontalArrowPositions: 'split',
        enableKeyboardNavigation: true,
        hideFocus: true,
        keyboardSpeed: 0,
        initialDelay: 300,
        speed: 30,
        scrollPagePercent: .8,
        keyDownCallback: {}
    };
})(jQuery, this);

//-------------------WebPDFNativeScroll----------------------------
(function($, window, undefined) {
    $.fn.WebPDFNativeScroll = function(settings) {
        function fwrJScrollPane(elem, s) {
            //elem = $('body'); // 测试去除doc viewer高度的时候滚动
            var settings, jsp = this;
            function initialise(s) {
                //ios  书签滚动 
                elem.css({
                    'overflow': 'auto'
                });
            }
            function Unimplemented(){
                $.error("Unimplemented function for native scroll bar.");
            }
            $.extend(jsp, {
                reinitialise: function(s) {
                    s = $.extend({},
                        settings, s);
                    initialise(s);
                },
                scrollToElement: function(ele, b1, b2, offsetY) {
                    var obj = null;
                    /*if($.support.touch){
                        obj = jQuery(ele).offset();
                        //obj.top -= elem.offset().top;
                    }else{*/
                        obj = jQuery(ele).position();
                  //  }
                    var top = obj.top;
                    if (offsetY) {
                        top = top + offsetY;
                    }
                    jsp.scrollBy(obj.left, top);
                },
                scrollTo: function(destX, destY, animate) {
                    elem.scrollLeft(destX);
                    elem.scrollTop(destY);
                },
                scrollToX: function(destX, animate) {
                    elem.scrollLeft(destX);
                },
                scrollToY: function(destY, animate) {
                    //elem.scrollTop(destY);
                    elem.css({"top" : -destY});
                },
                scrollToPercentX: function(destPercentX, animate) { Unimplemented();},
                scrollToPercentY: function(destPercentY, animate) { Unimplemented();},
                scrollBy: function(deltaX, deltaY, animate) {
                    jsp.scrollByX(deltaX, animate);
                    jsp.scrollByY(deltaY, animate);
                },
                scrollByX: function(deltaX, animate) {
                    if (elem.scrollLeft() <= 0 && deltaX < 0) deltaX = 0;
                    elem.scrollLeft(elem.scrollLeft() + deltaX);
                },
                scrollByY: function(deltaY, animate) {

                    /* if(WebPDF.Environment.mobile){
                         elem.css({"top" : parseInt(elem.css('top')) - deltaY});
                     }else{*/
                         if (elem.scrollTop() <= 0 && deltaY < 0) deltaY = 0;
                         elem.scrollTop(elem.scrollTop() + deltaY);
                    // }
                //    elem.css({"top" : parseInt(elem.css('top')) - deltaY}); //mobile
                    // elem.scrollTop(elem.scrollTop() + deltaY);
                },
                positionDragX: function(x, animate) { Unimplemented(); },
                positionDragY: function(y, animate) {Unimplemented(); },
                animate: function(ele, prop, value, stepCallback) { Unimplemented(); },
                getContentPositionX: function() {
                    return elem.scrollLeft();
                },
                getContentPositionY: function() {
                    return elem.scrollTop();
                },
                getContentWidth: function() { return elem.width(); },
                getContentHeight: function() { return elem.height(); },
                getPercentScrolledX: function() { Unimplemented(); },
                getPercentScrolledY: function() { Unimplemented(); },
                getIsScrollableH: function() {
                    return jsp.getScrollBarHeight() > 0;
                },
                getIsScrollableV: function() {
                    return jsp.getScrollBarWidth() > 0;
                }
                ,
                getScrollBarWidth: function(){
                    return elem[0].offsetWidth - elem[0].clientWidth;
                },
                getScrollBarHeight: function(){
                    return elem[0].offsetHeight - elem[0].clientHeight;
                },
                getContentPane: function() {
                    return elem;
                },
                scrollToBottom: function(animate) { Unimplemented(); },
                hijackInternalLinks: function() { Unimplemented(); },
                destroy: function() { Unimplemented(); }
            });
        }
        return this.each(function() {
            var elem = $(this),
                jspApi = elem.data('jsp');
            if (jspApi) {
                jspApi.reinitialise(settings);
            } else {
                jspApi = new fwrJScrollPane(elem, settings);
                elem.data('jsp', jspApi);
            }
        });
    };
})(jQuery, this);
//-----------------------------------------------
/*--------------------------------------------------|

 | dTree 2.05 | www.destroydrop.com/javascript/tree/ |

 |---------------------------------------------------|

 | Copyright (c) 2002-2003 Geir Landr?              |

 |                                                   |

 | This script can be used freely as long as all     |

 | copyright messages are intact.                    |

 |                                                   |

 | Updated: 17.04.2003                               |

 |--------------------------------------------------*/
/*--------------------------------------------------|

 | dTree 2.05 | www.destroydrop.com/javascript/tree/ |

 |---------------------------------------------------|

 | Copyright (c) 2002-2003 Geir Landr?              |

 |                                                   |

 | This script can be used freely as long as all     |

 | copyright messages are intact.                    |

 |                                                   |

 | Updated: 17.04.2003                               |

 |--------------------------------------------------*/

window.WebPDFTools = window.WebPDFTools || {};

WebPDFTools.Node = function(id, pid, name, url, title, target, icon, iconOpen, open) {
    this.id = id;
    this.pid = pid;
    this.name = name;
    this.url = url;
    this.title = title;
    this.target = target;
    this.icon = icon;
    this.iconOpen = iconOpen;
    this._io = open || false;
    this._is = false;
    this._ls = false;
    this._hc = false;
    this._ai = 0;
    this._hidden = false;
    this._bTop = false;
};
WebPDFTools.dTree = function(objName, extNodeClass, extPlusItemClass, icons) {
    this.config = {
        showroot: false,
        target: null,
        folderLinks: true,
        useSelection: true,
        useCookies: true,
        useLines: true,
        useIcons: true,
        useStatusText: false,
        closeSameLevel: false,
        inOrder: false
    };
    this.icon = icons;
    this.obj = objName;
    this.extNodeClass = extNodeClass;
    this.extPlusItemClass = extPlusItemClass;
    this.aNodes = [];
    this.aIndent = [];
    this.root = new WebPDFTools.Node( - 1);
    this.selectedNode = null;
    this.selectedFound = false;
    this.completed = false;
    this.bSetTop = false;
    this.curID = -1;
};
WebPDFTools.dTree.prototype.add = function(id, pid, name, url, title, target, icon, iconOpen, open) {
    this.aNodes[this.aNodes.length] = new WebPDFTools.Node(id, pid, name, url, title, target, icon, iconOpen, open);
};
WebPDFTools.dTree.prototype.openAll = function() {
    this.oAll(true);
};
WebPDFTools.dTree.prototype.closeAll = function() {
    this.oAll(false);
};
WebPDFTools.dTree.prototype.toString = function() {
    var str = '<div class="fwr-dtree">\n';
    if (document.getElementById) {
        if (this.config.useCookies) this.selectedNode = this.getSelected();
        str += this.addNode(this.root);
    } else str += 'Browser not supported.';
    str += '</div>';
    if (!this.selectedFound) this.selectedNode = null;
    this.completed = true;
    return str;
};
WebPDFTools.dTree.prototype.addNode = function(pNode) {
    var str = '';
    var n = 0;
    if (this.config.inOrder) n = pNode._ai;
    for (n; n < this.aNodes.length; n++) {
        if (this.aNodes[n].pid == pNode.id) {
            var cn = this.aNodes[n];
            cn._p = pNode;
            cn._ai = n;
            this.setCS(cn);
            if (!cn.target && this.config.target) cn.target = this.config.target;
            if (cn._hc && !cn._io && this.config.useCookies) cn._io = this.isOpen(cn.id);
            if (!this.config.folderLinks && cn._hc) cn.url = null;
            if (this.config.useSelection && cn.id == this.selectedNode && !this.selectedFound) {
                cn._is = true;
                this.selectedNode = n;
                this.selectedFound = true;
            }
            str += this.node(cn, n);
            if (cn._ls) break;
        }
    }
    return str;
};
WebPDFTools.dTree.prototype.node = function(node, nodeId) {
    var str = '<div class="fwr-dTreeNode"';
    if (this.root.id == node.pid && !this.config.showroot) {
        str += "style='display:none'";
        node._hidden = true;
    }
    str += ">";
    str += this.indent(node, nodeId);
    if (this.config.useIcons) {
        if (!node.icon) node.icon = (this.root.id == node.pid) ? this.icon.root: ((node._hc) ? this.icon.folder: this.icon.node);
        if (!node.iconOpen) node.iconOpen = (node._hc) ? this.icon.folderOpen: this.icon.node;
        if (this.root.id == node.pid) {
            node.icon = this.icon.root;
            node.iconOpen = this.icon.root;
            if (!this.config.showroot) node._hidden = true;
        }
        str += '<img id="i' + this.obj + nodeId + '" src="' + ((node._io) ? node.iconOpen: node.icon) + '" alt="" class="' + this.extNodeClass + '" nodeId="' + nodeId + '"/>';
    }
    if (node.url) {
        str += '<a id="s' + this.obj + nodeId + '" class="' + ((this.config.useSelection) ? ((node._is ? 'nodeSel': 'node')) : 'node') + '" href="' + node.url + '"';
        if (node.title) str += ' title="' + node.title + '"';
        if (node.target) str += ' target="' + node.target + '"';
        if (this.config.useStatusText) str += ' onmouseover="window.status=\'' + node.name + '\';return true;" onmouseout="window.status=\'\';return true;" ';
        if (this.config.useSelection && ((node._hc && this.config.folderLinks) || !node._hc)) str += ' onclick="javascript: ' + this.obj + '.s(' + nodeId + ');"';
        str += '>';
    } else if ((!this.config.folderLinks || !node.url) && node._hc && node.pid != this.root.id) str += '<a id="s' + this.obj + nodeId + '"" class="node ' + this.extNodeClass + '" nodeId="' + nodeId + '">';
    else str += '<a class="node ' + this.extNodeClass + '" nodeId="' + nodeId + '">';
    str += "<span id='" + this.obj + nodeId + "'title='" + node.name + "' class='" + this.extNodeClass + "' nodeId='" + nodeId + "'>" + node.name + "</span>";
    str += '</a>';
    str += '</div>';
    if (node._hc) {
        str += '<div id="d' + this.obj + nodeId + '" class="clip" style="display:' + ((this.root.id == node.pid || node._io) ? 'block': 'none') + ';">';
        str += this.addNode(node);
        str += '</div>';
    }
    this.aIndent.pop();
    return str;
};
WebPDFTools.dTree.prototype.indent = function(node, nodeId) {
    var str = '';
    if (this.root.id != node.pid) {
        if (!this.config.showroot && this.bSetTop == false) {
            node._bTop = true;
            this.bSetTop = true;
        }
        for (var n = 0; n < this.aIndent.length; n++) str += '<img src="' + ((this.aIndent[n] == 1 && this.config.useLines) ? this.icon.line: this.icon.empty) + '" alt="" />'; (node._ls) ? this.aIndent.push(0) : this.aIndent.push(1);
        if (node._hc) {
            var minusTB = !this.config.showroot && node._bTop ? this.icon.minusTop: this.icon.minus;
            var plusTB = !this.config.showroot && node._bTop ? this.icon.plusTop: this.icon.plus;
            var minusbottom = node._bTop == node._ls ? this.icon.minusOnly: this.icon.minusBottom;
            var plusbottom = node._bTop == node._ls ? this.icon.plusOnly: this.icon.plusBottom;
            str += '<a id="hc' + this.obj + nodeId + '" class="' + this.extPlusItemClass + '" nodeId="' + nodeId + '"><img id="j' + this.obj + nodeId + '" class="' + this.extPlusItemClass + '" nodeId="' + nodeId + '" src="';
            if (!this.config.useLines) str += (node._io) ? this.icon.nlMinus: this.icon.nlPlus;
            else str += ((node._io) ? ((node._ls && this.config.useLines) ? minusbottom: minusTB) : ((node._ls && this.config.useLines) ? plusbottom: plusTB));
            str += '" alt="" /></a>';
        } else {
            var joinTB = !this.config.showroot && node._bTop ? this.icon.joinTop: this.icon.join;
            var joinBottom = node._bTop == node._ls ? this.icon.joinonly: this.icon.joinBottom;
            str += '<img src="' + ((this.config.useLines) ? ((node._ls) ? joinBottom: joinTB) : this.icon.empty) + '" alt="" />';
        }
    }
    return str;
};
WebPDFTools.dTree.prototype.setCS = function(node) {
    var lastId;
    for (var n = 0; n < this.aNodes.length; n++) {
        if (this.aNodes[n].pid == node.id) node._hc = true;
        if (this.aNodes[n].pid == node.pid) lastId = this.aNodes[n].id;
    }
    if (lastId == node.id && !node._bTop) node._ls = true;
};
WebPDFTools.dTree.prototype.getSelected = function() {
    var sn = this.getCookie('cs' + this.obj);
    return (sn) ? sn: null;
};
WebPDFTools.dTree.prototype.s = function(id) {
    if (!this.config.useSelection) return;
    var cn = this.aNodes[id];
    if (cn._hc && !this.config.folderLinks) return;
    if (this.selectedNode != id) {
        if (this.selectedNode || this.selectedNode == 0) {
            eOld = document.getElementById("s" + this.obj + this.selectedNode);
            eOld.className = "node";
        }
        eNew = document.getElementById("s" + this.obj + id);
        eNew.className = "nodeSel";
        this.selectedNode = id;
        if (this.config.useCookies) this.setCookie('cs' + this.obj, cn.id);
    }
};
WebPDFTools.dTree.prototype.setCurNode = function(id) {
    if (this.config.useIcons && this.curID != id) {
        var eIcon = null;
        var eTitle = null;
        if (this.curID > -1) {
            eIcon = document.getElementById('i' + this.obj + this.curID);
            eIcon.src = this.icon.node;
            eTitle = document.getElementById(this.obj + this.curID).parentNode;
            eTitle.className= "bookmarkNode";
        }
        this.curID = id;
        eIcon = document.getElementById('i' + this.obj + this.curID);
        eTitle = document.getElementById(this.obj + this.curID).parentNode;
        eIcon.src = this.icon.nodehot;
        eTitle.className = "bookmarkNode nodeSel";
    }
};
WebPDFTools.dTree.prototype.o = function(id) {
    var cn = this.aNodes[id];
    this.nodeStatus(!cn._io, id, cn._ls);
    cn._io = !cn._io;
    if (this.config.closeSameLevel) this.closeLevel(cn);
    if (this.config.useCookies) this.updateCookie();
};
WebPDFTools.dTree.prototype.oAll = function(status) {
    for (var n = 0; n < this.aNodes.length; n++) {
        if (this.aNodes[n]._hc && this.aNodes[n].pid != this.root.id) {
            this.nodeStatus(status, n, this.aNodes[n]._ls);
            this.aNodes[n]._io = status;
        }
    }
    if (this.config.useCookies) this.updateCookie();
};
WebPDFTools.dTree.prototype.openTo = function(nId, bSelect, bFirst) {
    if (!bFirst) {
        for (var n = 0; n < this.aNodes.length; n++) {
            if (this.aNodes[n].id == nId) {
                nId = n;
                break;
            }
        }
    }
    var cn = this.aNodes[nId];
    if (cn.pid == this.root.id || !cn._p) return;
    cn._io = true;
    cn._is = bSelect;
    if (this.completed && cn._hc) this.nodeStatus(true, cn._ai, cn._ls);
    if (this.completed && bSelect) this.s(cn._ai);
    else if (bSelect) this._sn = cn._ai;
    this.openTo(cn._p._ai, false, true);
};
WebPDFTools.dTree.prototype.closeLevel = function(node) {
    for (var n = 0; n < this.aNodes.length; n++) {
        if (this.aNodes[n].pid == node.pid && this.aNodes[n].id != node.id && this.aNodes[n]._hc) {
            this.nodeStatus(false, n, this.aNodes[n]._ls);
            this.aNodes[n]._io = false;
            this.closeAllChildren(this.aNodes[n]);
        }
    }
};
WebPDFTools.dTree.prototype.closeAllChildren = function(node) {
    for (var n = 0; n < this.aNodes.length; n++) {
        if (this.aNodes[n].pid == node.id && this.aNodes[n]._hc) {
            if (this.aNodes[n]._io) this.nodeStatus(false, n, this.aNodes[n]._ls);
            this.aNodes[n]._io = false;
            this.closeAllChildren(this.aNodes[n]);
        }
    }
};
WebPDFTools.dTree.prototype.nodeStatus = function(status, id, bottom) {
    eDiv = document.getElementById('d' + this.obj + id);
    eJoin = document.getElementById('j' + this.obj + id);
    var bTop = this.aNodes[id]._bTop;
    var minusTB = !this.config.showroot && bTop ? this.icon.minusTop: this.icon.minus;
    var plusTB = !this.config.showroot && bTop ? this.icon.plusTop: this.icon.plus;
    var minusbottom = bTop == bottom ? this.icon.minusOnly: this.icon.minusBottom;
    var plusbottom = bTop == bottom ? this.icon.plusOnly: this.icon.plusBottom;
    eJoin.src = (this.config.useLines) ? ((status) ? ((bottom) ? minusbottom: minusTB) : ((bottom) ? plusbottom: plusTB)) : ((status) ? this.icon.nlMinus: this.icon.nlPlus);
    eDiv.style.display = (status) ? 'block': 'none';
};
WebPDFTools.dTree.prototype.clearCookie = function() {
    var now = new Date();
    var yesterday = new Date(now.getTime() - 1000 * 60 * 60 * 24);
    this.setCookie('co' + this.obj, 'cookieValue', yesterday);
    this.setCookie('cs' + this.obj, 'cookieValue', yesterday);
};
WebPDFTools.dTree.prototype.setCookie = function(cookieName, cookieValue, expires, path, domain, secure) {
    document.cookie = escape(cookieName) + '=' + escape(cookieValue) + (expires ? '; expires=' + expires.toGMTString() : '') + (path ? '; path=' + path: '') + (domain ? '; domain=' + domain: '') + (secure ? '; secure': '');
};
WebPDFTools.dTree.prototype.getCookie = function(cookieName) {
    var cookieValue = '';
    var posName = document.cookie.indexOf(escape(cookieName) + '=');
    if (posName != -1) {
        var posValue = posName + (escape(cookieName) + '=').length;
        var endPos = document.cookie.indexOf(';', posValue);
        if (endPos != -1) cookieValue = unescape(document.cookie.substring(posValue, endPos));
        else cookieValue = unescape(document.cookie.substring(posValue));
    }
    return (cookieValue);
};
WebPDFTools.dTree.prototype.updateCookie = function() {
    var str = '';
    for (var n = 0; n < this.aNodes.length; n++) {
        if (this.aNodes[n]._io && this.aNodes[n].pid != this.root.id) {
            if (str) str += '.';
            str += this.aNodes[n].id;
        }
    }
    this.setCookie('co' + this.obj, str);
};
WebPDFTools.dTree.prototype.isOpen = function(id) {
    var aOpen = this.getCookie('co' + this.obj).split('.');
    for (var n = 0; n < aOpen.length; n++) if (aOpen[n] == id) return true;
    return false;
};
if (!Array.prototype.push) {
    Array.prototype.push = function array_push() {
        for (var i = 0; i < arguments.length; i++) this[this.length] = arguments[i];
        return this.length;
    };
}
if (!Array.prototype.pop) {
    Array.prototype.pop = function array_pop() {
        lastElement = this[this.length - 1];
        this.length = Math.max(this.length - 1, 0);
        return lastElement;
    };
};



